package camid.main.jmeter;

import java.util.Iterator;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;

import camid.distribution.activeobject.ProxyExecutorManager;
import camid.main.ClientFacade;
import camid.services.nameservice.INameService;
import camid.test.testobjects.DelayObject;
import camid.test.testobjects.IDelayObject;

public class CamidAdaptiveElasticClient extends AbstractJavaSamplerClient implements JavaSamplerClient
{

	public static final Long DEFAULT_DELAY = 100L;
	public static final String DEFAULT_NSHOST = "127.0.0.1";
	public static final Integer DEFAULT_NSPORT = 15001;
	private static final String DEFAULT_OBJECT = DelayObject.class.getCanonicalName();

	public static final Long DEFAULT_WAIT_INTERVAL = 90000L;

	private String nshost;
	private Integer nsport;
	private Long delay;
	private String object;

	private Class<?> remoteClass;

	private CamidJmeterElasticAgent agent;
	
	private static AtomicInteger objectCounter = new AtomicInteger(0);
	

	private IDelayObject delayObject;
	
	public CamidAdaptiveElasticClient()
	{
		super();
		agent = CamidJmeterElasticAgent.getInstance();
		agent.startBaseSystem();
	}

	@Override
	public SampleResult runTest(JavaSamplerContext samplerContext) {
		SampleResult result = new SampleResult();

		try
		{
			result.sampleStart();
			if(delayObject == null)
			{
				delayObject = ClientFacade.getInstance().lookupObject(IDelayObject.class, remoteClass);
			}
			delayObject.doDelay(delay);
			result.setSuccessful(true);
		}
		catch(Exception e)
		{
			e.printStackTrace();
			result.setSuccessful(false);
		}
		finally
		{
			result.sampleEnd();
		}

		return result;
	}

	private String whoAmI() {
		StringBuilder sb = new StringBuilder();
		sb.append(Thread.currentThread().toString());
		sb.append("@");
		sb.append(Integer.toHexString(hashCode()));
		return sb.toString();
	}

	@Override
	public Arguments getDefaultParameters() {
		Arguments params = new Arguments();
		params.addArgument("object", String.valueOf(DEFAULT_OBJECT));
		params.addArgument("delay", String.valueOf(DEFAULT_DELAY));
		params.addArgument("waitInterval", String.valueOf(DEFAULT_WAIT_INTERVAL));

		return params;
	}

	public void setupTest(JavaSamplerContext context) {
		getLogger().debug(whoAmI() + "\tsetupTest()");
		listParameters(context);

		this.agent.startAllWorkers();
		
		EnviromentVariableHandler handler = EnviromentVariableHandler.getInstance();

		nshost = handler.getMainNode() != null ? handler.getMainNode() : DEFAULT_NSHOST;
		nsport = handler.getPort() != null ? handler.getPort() : DEFAULT_NSPORT;
		
		
		delay = context.getLongParameter("delay", DEFAULT_DELAY);
		object = context.getParameter("object", DEFAULT_OBJECT);

		ClientFacade client = ClientFacade.getInstance();
		client.remoteNameService(nshost, nsport);
		
		try {
			remoteClass = Class.forName(object);
			
			while(delayObject == null)
			{
				delayObject = client.lookupObject(IDelayObject.class, remoteClass);
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
//		super.setupTest(context);
	}

	@Override
	public void teardownTest(JavaSamplerContext context) 
	{
		getLogger().debug(whoAmI() + "\tteardownTest()");
		ProxyExecutorManager.getInstance().shutdownExecutors();
		ClientFacade.getInstance().shutdownSenderQueue();
		CamidJmeterElasticAgent.getInstance().shutdown();
		super.teardownTest(context);

	}

	private void listParameters(JavaSamplerContext context) 
	{
		if (getLogger().isDebugEnabled()) {
			Iterator<String> argsIt = context.getParameterNamesIterator();
			while (argsIt.hasNext()) 
			{
				String name = argsIt.next();
				getLogger().debug(name + "=" + context.getParameter(name));
			}
		}
	}

	public static void main(String[] args) {

		Thread t = new Thread(new ThreadGroup("TG-Main"), new Runnable() {

			@Override
			public void run() {
				Arguments jmargs = new Arguments();
				jmargs.addArgument("object", String.valueOf(DEFAULT_OBJECT));
				jmargs.addArgument("delay", String.valueOf(DEFAULT_DELAY));
				jmargs.addArgument("waitInterval", String.valueOf(100));

				JavaSamplerContext context = new JavaSamplerContext(jmargs);
				//		JavaSamplerContext context = new JavaSamplerContext()
				CamidAdaptiveElasticClient client = new CamidAdaptiveElasticClient();
				client.setupTest(context);

				client.runTest(context);
				
			}
			
		});
		t.start();


	}

}
